﻿using System;
using Blockey.GameObjects3D;
using BlockeyEssentials;
using BlockeyEssentials.Input;
using BlockeyEssentials.ScreenSystem;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using System.Collections.Generic;

namespace Blockey.GameplayScreens
{
    public class HockeyGameScreen3D : MatchScreen3D
    {
        public HockeyGameScreen3D(ScreenManager oManager)
            : base(oManager)
        {
        }

        #region Methods

        public override void ActionWhenFullyAdded()
        {
            if (Networking.IsRunning)
            {
                HookEvents();
            }
        }

        protected override void SendClientToHost()
        {
            base.SendClientToHost();
        }

        protected override void SendHostToClients()
        {
            base.SendHostToClients();
        }

        protected override void ClientReceiveFromHost()
        {
            foreach (var oLocal in Networking.Session.LocalGamers)
            {
                if (oLocal.IsHost == false)
                {
                    while (oLocal.IsDataAvailable)
                    {
                        NetworkGamer oHost;
                        oLocal.ReceiveData(Networking.Reader, out oHost);

                        foreach (var oGamer in Networking.Session.AllGamers)
                        {
                            var oPerson = oGamer.Tag as Person3D;
                            var x = (float)Networking.Reader.ReadInt16() * 0.01f;
                            var y = (float)Networking.Reader.ReadInt16() * 0.01f;
                            oPerson.PositionDestination = new Vector3(x, y, 0);
                            oPerson.PrevPosition = oPerson.Position;

                            var oRotation = oPerson.Rotation;
                            oRotation.Z = MathHelper.ToRadians(Networking.Reader.ReadInt16());
                            oPerson.Rotation = oRotation;

                            var oCondition = (ConditionName)Networking.Reader.ReadByte();
                            if (oPerson.Condition.Name != oCondition)
                            {
                                oPerson.Condition.ChangeTypeForClient(oCondition);
                                oPerson.StartCondition(false);
                            }
                        }
                    }
                }
            }
        }

        protected override void HandleCollision(Moveable3D oMoveA, Moveable3D oMoveB)
        {
            var oPersonA = oMoveA as Person3D;
            var oPersonB = oMoveB as Person3D;
            var oSkaterA = oMoveA as Skater;
            var oSkaterB = oMoveB as Skater;
            var oGoalieA = oMoveA as Goalie;
            var oGoalieB = oMoveB as Goalie;
            var oPuckA = oMoveA as Puck3D;
            var oPuckB = oMoveB as Puck3D;

            bool bCollision = (oMoveA.CollidesWith(oMoveB));

            if (oPersonA != null && oPersonB != null && bCollision)
            {
                var oConditionA = oPersonA.Condition.Name;
                var oConditionB = oPersonB.Condition.Name;

                if (oConditionA == ConditionName.Tackling)
                {
                    if (oConditionB == ConditionName.Neutral)
                    {
                        oPersonA.Condition.ChangeTypeToNeutral();
                        oPersonA.StartCondition(true);

                        oPersonB.Fall();
                        oPersonB.StartCondition(true);

                        if (oPersonB.HeldObjects.Contains(Puck))
                        {
                            oPersonB.HeldObjects.Remove(Puck);
                        }
                    }
                }
                else if (oConditionB == ConditionName.Tackling)
                {
                    if (oConditionA == ConditionName.Neutral)
                    {
                        oPersonB.Condition.ChangeTypeToNeutral();
                        oPersonB.StartCondition(true);

                        oPersonA.Fall();
                        oPersonA.StartCondition(true);

                        if (oPersonA.HeldObjects.Contains(Puck))
                        {
                            oPersonA.HeldObjects.Remove(Puck);
                        }
                    }
                }
                else
                {
                    base.HandleCollision(oMoveA, oMoveB);
                }
            }
            else if (oSkaterA != null && oGoalieB != null)
            {
                if (bCollision)
                {
                    oSkaterA.Condition.ChangeType(ConditionName.Falling, Condition.ENDTIME_FALLING);
                    oSkaterA.StartCondition(true);
                    oGoalieB.Condition.ChangeTypeToNeutral();
                    oGoalieB.StartCondition(true);

                    if (oSkaterA.HeldObjects.Contains(Puck))
                    {
                        oSkaterA.HeldObjects.Remove(Puck);
                    }
                }

                base.HandleCollision(oMoveA, oMoveB);
            }
            else if (oSkaterB != null && oGoalieA != null)
            {
                if (bCollision)
                {
                    oSkaterB.Condition.ChangeType(ConditionName.Falling, Condition.ENDTIME_FALLING);
                    oSkaterB.StartCondition(true);
                    oGoalieA.Condition.ChangeTypeToNeutral();
                    oGoalieA.StartCondition(true);

                    if (oSkaterB.HeldObjects.Contains(Puck))
                    {
                        oSkaterB.HeldObjects.Remove(Puck);
                    }
                }

                base.HandleCollision(oMoveA, oMoveB);
            }
            else if (oPuckA != null && oGoalieB != null)
            {
                if (oPuckA.CollidesWith(oGoalieB.PuckCollisionTop) || oPuckA.CollidesWith(oGoalieB.PuckCollisionBottom))
                {
                    if (oGoalieB.TeamSide == Alliance.Home)
                    {
                        oMoveA.VelocityX = Math.Abs(oMoveA.VelocityX);
                        oMoveA.VelocityX = Math.Max(oMoveA.VelocityX, 0.5f);
                    }
                    else
                    {
                        oMoveA.VelocityX = -Math.Abs(oMoveA.VelocityX);
                        oMoveA.VelocityX = Math.Min(oMoveA.VelocityX, -0.5f);
                    }
                }
            }
            else if (oPuckB != null && oGoalieA != null)
            {
                if (oPuckB.CollidesWith(oGoalieA.PuckCollisionTop) || oPuckB.CollidesWith(oGoalieA.PuckCollisionBottom))
                {
                    if (oGoalieB.TeamSide == Alliance.Home)
                    {
                        oMoveB.VelocityX = Math.Abs(oMoveB.VelocityX);
                        oMoveB.VelocityX = Math.Max(oMoveB.VelocityX, 0.5f);
                    }
                    else
                    {
                        oMoveB.VelocityX = -Math.Abs(oMoveB.VelocityX);
                        oMoveB.VelocityX = Math.Min(oMoveB.VelocityX, -0.5f);
                    }
                }
            }
            else
            {
                base.HandleCollision(oMoveA, oMoveB);
            }
        }

        protected override void ArenaCollision()
        {
            base.ArenaCollision();

            foreach (var oMoveable in m_oMoveables)
            {
                AwayGoal.CollisionWith(oMoveable);
                HomeGoal.CollisionWith(oMoveable);
            }
        }

        #endregion

        #region Network Session Events

        private static void HookEvents()
        {
            if (Networking.Session.IsHost)
            {
                Networking.Session.AllowJoinInProgress = true;
                Networking.Session.AllowHostMigration = true;
            }
            Networking.Session.GamerJoined += new EventHandler<GamerJoinedEventArgs>(session_GamerJoined);
            Networking.Session.GamerLeft += new EventHandler<GamerLeftEventArgs>(session_GamerLeft);
            Networking.Session.GameStarted += new EventHandler<GameStartedEventArgs>(session_GameStarted);
            Networking.Session.HostChanged += new EventHandler<HostChangedEventArgs>(session_HostChanged);
            Networking.Session.GameEnded += new EventHandler<GameEndedEventArgs>(session_GameEnded);
        }

        // Fired when the game ends
        static void session_GameEnded(object sender, GameEndedEventArgs e)
        {

        }

        // Triggered when the host is changed
        static void session_HostChanged(object sender, HostChangedEventArgs e)
        {
            var oPersonOld = e.OldHost.Tag as Person3D;
            var oPersonNew = e.NewHost.Tag as Person3D;

            if (oPersonOld != null && oPersonNew != null)
            {

            }
        }

        // Triggered when the game starts 
        static void session_GameStarted(object sender, GameStartedEventArgs e)
        {

        }

        // Triggered when a gamer leaves the game
        static void session_GamerLeft(object sender, GamerLeftEventArgs e)
        {
            var oPerson = e.Gamer.Tag as Person3D;

            if (oPerson != null)
            {
                RemoveObject(oPerson);
                e.Gamer.Tag = null;
            }
        }

        // Triggered when a gamer joins the game
        static void session_GamerJoined(object sender, GamerJoinedEventArgs e)
        {
            var oGamer = e.Gamer;
            var oPerson = new Skater(All.CurrentScreenManager.Game, ControllingPlayer.AI, Alliance.Home);

            AddObject(oPerson);
            e.Gamer.Tag = oPerson;
        }

        #endregion

        //private IntroTestScreen m_oIntroScreen;



    }
}
